from typing import List, Optional, Dict, Any
import logging
from datetime import datetime

from app.storage.json_storage import storage
from app.models.schemas import TaskConfig, TaskInfo, TaskStatus, TaskListParams, PaginatedResponse
from app.services.crawl_service import MockCrawlService

logger = logging.getLogger(__name__)

class JSONTaskService:
    """基于JSON文件的任务服务"""
    
    def __init__(self):
        self.crawl_service = MockCrawlService()
    
    def create_task(self, config: TaskConfig) -> TaskInfo:
        """创建新任务"""
        try:
            # 准备任务数据
            task_data = {
                'name': config.name,
                'description': config.description or "",
                'urls': config.urls,
                'config': self._config_to_dict(config)
            }
            
            # 创建任务
            new_task = storage.create_task(task_data)
            
            # 添加日志
            storage.add_log({
                'level': 'INFO',
                'message': f'Task created: {new_task["name"]}',
                'task_id': new_task['id']
            })
            
            logger.info(f"Task created: {new_task['id']}")
            return self._dict_to_task_info(new_task)
            
        except Exception as e:
            logger.error(f"Failed to create task: {e}")
            raise
    
    def get_task(self, task_id: str) -> Optional[TaskInfo]:
        """获取任务详情"""
        try:
            task = storage.get_task_by_id(task_id)
            if task:
                return self._dict_to_task_info(task)
            return None
        except Exception as e:
            logger.error(f"Failed to get task {task_id}: {e}")
            return None
    
    def list_tasks(self, params: TaskListParams) -> PaginatedResponse:
        """获取任务列表"""
        try:
            all_tasks = storage.get_tasks()
            
            # 状态过滤
            if params.status:
                all_tasks = [task for task in all_tasks if task['status'] == params.status.value]
            
            # 搜索过滤
            if params.search:
                search_lower = params.search.lower()
                all_tasks = [
                    task for task in all_tasks 
                    if search_lower in task['name'].lower() or 
                       search_lower in task.get('description', '').lower()
                ]
            
            # 排序（按创建时间倒序）
            all_tasks.sort(key=lambda x: x['created_at'], reverse=True)
            
            # 分页
            total = len(all_tasks)
            start_idx = (params.page - 1) * params.size
            end_idx = start_idx + params.size
            tasks = all_tasks[start_idx:end_idx]
            
            # 转换为TaskInfo
            items = [self._dict_to_task_info(task) for task in tasks]
            
            return PaginatedResponse(
                items=items,
                total=total,
                page=params.page,
                size=params.size,
                pages=(total + params.size - 1) // params.size
            )
            
        except Exception as e:
            logger.error(f"Failed to list tasks: {e}")
            raise
    
    def update_task(self, task_id: str, config: TaskConfig) -> Optional[TaskInfo]:
        """更新任务"""
        try:
            # 准备更新数据
            update_data = {
                'name': config.name,
                'description': config.description or "",
                'urls': config.urls,
                'config': self._config_to_dict(config)
            }
            
            # 更新任务
            updated_task = storage.update_task(task_id, update_data)
            if not updated_task:
                return None
            
            # 添加日志
            storage.add_log({
                'level': 'INFO',
                'message': f'Task updated: {updated_task["name"]}',
                'task_id': task_id
            })
            
            logger.info(f"Task updated: {task_id}")
            return self._dict_to_task_info(updated_task)
            
        except Exception as e:
            logger.error(f"Failed to update task {task_id}: {e}")
            raise
    
    def delete_task(self, task_id: str) -> bool:
        """删除任务"""
        try:
            # 获取任务信息用于日志
            task = storage.get_task_by_id(task_id)
            if not task:
                return False
            
            # 删除任务
            success = storage.delete_task(task_id)
            
            if success:
                # 添加日志
                storage.add_log({
                    'level': 'INFO',
                    'message': f'Task deleted: {task["name"]}',
                    'task_id': task_id
                })
                
                logger.info(f"Task deleted: {task_id}")
            
            return success
            
        except Exception as e:
            logger.error(f"Failed to delete task {task_id}: {e}")
            raise
    
    def start_task(self, task_id: str) -> bool:
        """启动任务"""
        try:
            task = storage.get_task_by_id(task_id)
            if not task:
                return False
            
            if task['status'] in ["running"]:
                logger.warning(f"Task {task_id} is already running")
                return False
            
            # 更新任务状态
            update_data = {
                'status': 'running',
                'started_at': datetime.utcnow().isoformat(),
                'progress': 0.0,
                'pages_crawled': 0,
                'pages_total': len(task['urls']),
                'errors_count': 0
            }
            
            # 添加启动日志到任务的logs字段
            task_logs = task.get('logs', [])
            task_logs.append({
                'timestamp': datetime.utcnow().isoformat(),
                'level': 'INFO',
                'message': f'Task {task_id} started'
            })
            update_data['logs'] = task_logs
            
            storage.update_task(task_id, update_data)
            
            # 添加系统日志
            storage.add_log({
                'level': 'INFO',
                'message': f'Task started: {task["name"]}',
                'task_id': task_id
            })
            
            # 这里可以启动实际的爬取任务
            # self.crawl_service.start_crawl(task_id, task['config'])
            
            logger.info(f"Task started: {task_id}")
            return True
            
        except Exception as e:
            logger.error(f"Failed to start task {task_id}: {e}")
            raise
    
    def stop_task(self, task_id: str) -> bool:
        """停止任务"""
        try:
            task = storage.get_task_by_id(task_id)
            if not task:
                return False
            
            if task['status'] not in ["running"]:
                logger.warning(f"Task {task_id} is not running")
                return False
            
            # 更新任务状态
            update_data = {
                'status': 'stopped',
                'completed_at': datetime.utcnow().isoformat()
            }
            
            # 添加停止日志到任务的logs字段
            task_logs = task.get('logs', [])
            task_logs.append({
                'timestamp': datetime.utcnow().isoformat(),
                'level': 'INFO',
                'message': f'Task {task_id} stopped'
            })
            update_data['logs'] = task_logs
            
            storage.update_task(task_id, update_data)
            
            # 添加系统日志
            storage.add_log({
                'level': 'INFO',
                'message': f'Task stopped: {task["name"]}',
                'task_id': task_id
            })
            
            logger.info(f"Task stopped: {task_id}")
            return True
            
        except Exception as e:
            logger.error(f"Failed to stop task {task_id}: {e}")
            raise
    
    def get_task_status(self, task_id: str) -> Optional[Dict[str, Any]]:
        """获取任务状态"""
        try:
            task = storage.get_task_by_id(task_id)
            if not task:
                return None
            
            return {
                "task_id": task_id,
                "status": task['status'],
                "progress": task['progress'],
                "pages_crawled": task['pages_crawled'],
                "pages_total": task['pages_total'],
                "success_rate": task['success_rate'],
                "errors_count": task['errors_count'],
                "started_at": task.get('started_at'),
                "updated_at": task['updated_at']
            }
            
        except Exception as e:
            logger.error(f"Failed to get task status {task_id}: {e}")
            return None
    
    def get_task_logs(self, task_id: str, limit: int = 100) -> List[Dict[str, Any]]:
        """获取任务日志"""
        try:
            # 获取任务内部日志
            task = storage.get_task_by_id(task_id)
            task_logs = task.get('logs', []) if task else []
            
            # 获取系统日志
            system_logs = storage.get_logs(task_id=task_id, limit=limit)
            
            # 合并并排序日志
            all_logs = task_logs + [
                {
                    'timestamp': log['timestamp'],
                    'level': log['level'],
                    'message': log['message']
                }
                for log in system_logs
            ]
            
            # 按时间排序
            all_logs.sort(key=lambda x: x['timestamp'], reverse=True)
            
            return all_logs[:limit]
            
        except Exception as e:
            logger.error(f"Failed to get task logs {task_id}: {e}")
            return []
    
    def _dict_to_task_info(self, task_dict: dict) -> TaskInfo:
        """将字典转换为TaskInfo"""
        return TaskInfo(
            id=task_dict['id'],
            name=task_dict['name'],
            description=task_dict.get('description', ''),
            urls=task_dict.get('urls', []),
            status=TaskStatus(task_dict['status']),
            progress=task_dict.get('progress', 0.0),
            pages_crawled=task_dict.get('pages_crawled', 0),
            pages_total=task_dict.get('pages_total', 0),
            success_rate=task_dict.get('success_rate', 0.0),
            errors_count=task_dict.get('errors_count', 0),
            config=task_dict.get('config', {}),
            created_at=datetime.fromisoformat(task_dict['created_at']),
            updated_at=datetime.fromisoformat(task_dict['updated_at']),
            started_at=datetime.fromisoformat(task_dict['started_at']) if task_dict.get('started_at') else None,
            completed_at=datetime.fromisoformat(task_dict['completed_at']) if task_dict.get('completed_at') else None
        )
    
    def _config_to_dict(self, config: TaskConfig) -> Dict[str, Any]:
        """将TaskConfig转换为字典"""
        if hasattr(config, 'dict'):
            return config.dict()
        elif hasattr(config, '__dict__'):
            return config.__dict__
        else:
            return {}
